﻿#ifndef XVARIANT_INTERFACE_HPP
#define XVARIANT_INTERFACE_HPP

#include "xvariant_tool.hpp"
#include "xvariant.hpp"
#include <lpb_reflect/xvariantDef.hpp>

namespace NS_variant
{
	template<typename T,T m>
	struct wrapper_member
	{
		using mem_t = typename getMemberType<T>::member_t;
		static void set_property_ptr(void* pobject, myVariant t) {
			if (!t.isValid<mem_t>()) {
				std::cout << "input property value is invalid!\n";
				return;
			}
			using obj_t = typename getMemberType<T>::class_t;
			obj_t* pobj = (obj_t*)pobject;
			(pobj->*m) = t.get<mem_t>();
		}

		static void set_property_wrapperPtr(myVariant t0, myVariant t) {
			if (!t.isValid<mem_t>()) {
				std::cout << "input property value is invalid!\n";
				return;
			}
			using obj_t = typename getMemberType<T>::class_t;
			obj_t* pobject = nullptr;
			if (t0.isValid<obj_t*>()) {
				pobject = t0.get<obj_t*>();
			}
			if (t0.isValid<std::shared_ptr<obj_t>>()) {
				auto ptr = t0.get<std::shared_ptr<obj_t>>();
				pobject = ptr.get();
			}

			obj_t* pobj = (obj_t*)pobject;
			(pobj->*m) = t.get<mem_t>();
		}

		static myVariant get_property_ptr(void* pobject) {
			using obj_t = typename getMemberType<T>::class_t;
			obj_t* pobj = (obj_t*)pobject;
			return (pobj->*m);
		}

		static myVariant get_property_wrapperPtr(myVariant t0) {
			using obj_t = typename getMemberType<T>::class_t;
			obj_t* pobject = nullptr;
			if (t0.isValid<obj_t*>()) {
				pobject = t0.get<obj_t*>();
			}
			if (t0.isValid<std::shared_ptr<obj_t>>()) {
				auto ptr = t0.get<std::shared_ptr<obj_t>>();
				pobject = ptr.get();
			}

			obj_t* pobj = (obj_t*)pobject;
			return (pobj->*m);
		}
	};

	template<typename T,T f>
	struct wrapper_Algorithm
	{
		static myVariant execute_ptr(void *pobject, 
			myVariant t1 = myVariant(),
			myVariant t2 = myVariant(),
			myVariant t3 = myVariant(), 
			myVariant t4 = myVariant(),
			myVariant t5 = myVariant(),
			myVariant t6 = myVariant(), 
			myVariant t7 = myVariant(), 
			myVariant t8 = myVariant(), 
			myVariant t9 = myVariant(), 
			myVariant t10 = myVariant()
		)
		{
			using obj_t = typename getFunparameters<T>::class_t;
			using return_t = typename getFunparameters<T>::ret_t;
			obj_t* pobj = (obj_t*)pobject;
			if constexpr (getFunparameters<T>::num == 10)
			{
				using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
				using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
				using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
				using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
				using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
				using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
				using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
				using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;
				using Arg9 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 8>>;
				using Arg10 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 9>>;

				if (!t1.isValid<Arg1>())
				{
					std::cout << "Arg1 invalid" << std::endl;
				}

				if (!t2.isValid<Arg2>())
				{
					std::cout << "Arg2 invalid" << std::endl;
				}

				if (!t3.isValid<Arg3>())
				{
					std::cout << "Arg3 invalid" << std::endl;
				}

				if (!t4.isValid<Arg4>())
				{
					std::cout << "Arg4 invalid" << std::endl;
				}

				if (!t5.isValid<Arg5>())
				{
					std::cout << "Arg5 invalid" << std::endl;
				}

				if (!t6.isValid<Arg6>())
				{
					std::cout << "Arg6 invalid" << std::endl;
				}

				if (!t7.isValid<Arg7>())
				{
					std::cout << "Arg7 invalid" << std::endl;
				}

				if (!t8.isValid<Arg8>())
				{
					std::cout << "Arg8 invalid" << std::endl;
				}

				if (!t9.isValid<Arg9>())
				{
					std::cout << "Arg9 invalid" << std::endl;
				}

				if (!t10.isValid<Arg10>())
				{
					std::cout << "Arg10 invalid" << std::endl;
				}

				if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
					 !t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>() || !t9.isValid<Arg9>() || !t10.isValid<Arg10>())
					return myVariant();

				auto v1 = t1.get_pointer<Arg1>();
				auto v2 = t2.get_pointer<Arg2>();
				auto v3 = t3.get_pointer<Arg3>();
				auto v4 = t4.get_pointer<Arg4>();
				auto v5 = t5.get_pointer<Arg5>();
				auto v6 = t6.get_pointer<Arg6>();
				auto v7 = t7.get_pointer<Arg7>();
				auto v8 = t8.get_pointer<Arg8>();
				auto v9 = t9.get_pointer<Arg9>();
				auto v10 = t10.get<Arg10>();
				if constexpr (std::is_same_v<return_t, void>) {
					(pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9, *v10);
					return myVariant();
				}
				else
					return (pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9, *v10);
			}
			else
			{
				if constexpr (getFunparameters<T>::num == 9)
				{
					using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
					using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
					using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
					using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
					using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
					using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
					using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
					using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;
					using Arg9 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 8>>;

					if (!t1.isValid<Arg1>())
					{
						std::cout << "Arg1 invalid" << std::endl;
					}

					if (!t2.isValid<Arg2>())
					{
						std::cout << "Arg2 invalid" << std::endl;
					}

					if (!t3.isValid<Arg3>())
					{
						std::cout << "Arg3 invalid" << std::endl;
					}

					if (!t4.isValid<Arg4>())
					{
						std::cout << "Arg4 invalid" << std::endl;
					}

					if (!t5.isValid<Arg5>())
					{
						std::cout << "Arg5 invalid" << std::endl;
					}

					if (!t6.isValid<Arg6>())
					{
						std::cout << "Arg6 invalid" << std::endl;
					}

					if (!t7.isValid<Arg7>())
					{
						std::cout << "Arg7 invalid" << std::endl;
					}

					if (!t8.isValid<Arg8>())
					{
						std::cout << "Arg8 invalid" << std::endl;
					}

					if (!t9.isValid<Arg9>())
					{
						std::cout << "Arg9 invalid" << std::endl;
					}

					if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
						!t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>() || !t9.isValid<Arg9>())
						return myVariant();

					auto v1 = t1.get_pointer<Arg1>();
					auto v2 = t2.get_pointer<Arg2>();
					auto v3 = t3.get_pointer<Arg3>();
					auto v4 = t4.get_pointer<Arg4>();
					auto v5 = t5.get_pointer<Arg5>();
					auto v6 = t6.get_pointer<Arg6>();
					auto v7 = t7.get_pointer<Arg7>();
					auto v8 = t8.get_pointer<Arg8>();
					auto v9 = t9.get_pointer<Arg9>();
					if constexpr (std::is_same_v<return_t, void>) {
						(pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9);
						return myVariant();
					}
					else
						return (pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9);
				}
				else{
					if constexpr (getFunparameters<T>::num == 8)
					{
						using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
						using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
						using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
						using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
						using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
						using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
						using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
						using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;

						if (!t1.isValid<Arg1>())
						{
							std::cout << "Arg1 invalid" << std::endl;
						}

						if (!t2.isValid<Arg2>())
						{
							std::cout << "Arg2 invalid" << std::endl;
						}

						if (!t3.isValid<Arg3>())
						{
							std::cout << "Arg3 invalid" << std::endl;
						}

						if (!t4.isValid<Arg4>())
						{
							std::cout << "Arg4 invalid" << std::endl;
						}

						if (!t5.isValid<Arg5>())
						{
							std::cout << "Arg5 invalid" << std::endl;
						}

						if (!t6.isValid<Arg6>())
						{
							std::cout << "Arg6 invalid" << std::endl;
						}

						if (!t7.isValid<Arg7>())
						{
							std::cout << "Arg7 invalid" << std::endl;
						}

						if (!t8.isValid<Arg8>())
						{
							std::cout << "Arg8 invalid" << std::endl;
						}

						if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
							!t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>() )
							return myVariant();

						auto v1 = t1.get_pointer<Arg1>();
						auto v2 = t2.get_pointer<Arg2>();
						auto v3 = t3.get_pointer<Arg3>();
						auto v4 = t4.get_pointer<Arg4>();
						auto v5 = t5.get_pointer<Arg5>();
						auto v6 = t6.get_pointer<Arg6>();
						auto v7 = t7.get_pointer<Arg7>();
						auto v8 = t8.get_pointer<Arg8>();
						if constexpr (std::is_same_v<return_t, void>) {
							(pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8);
							return myVariant();
						}
						else
							return (pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8);
					}else{
						if constexpr (getFunparameters<T>::num == 7)
						{
							using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
							using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
							using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
							using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
							using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
							using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
							using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;

							if (!t1.isValid<Arg1>())
							{
								std::cout << "Arg1 invalid" << std::endl;
							}

							if (!t2.isValid<Arg2>())
							{
								std::cout << "Arg2 invalid" << std::endl;
							}

							if (!t3.isValid<Arg3>())
							{
								std::cout << "Arg3 invalid" << std::endl;
							}

							if (!t4.isValid<Arg4>())
							{
								std::cout << "Arg4 invalid" << std::endl;
							}

							if (!t5.isValid<Arg5>())
							{
								std::cout << "Arg5 invalid" << std::endl;
							}

							if (!t6.isValid<Arg6>())
							{
								std::cout << "Arg6 invalid" << std::endl;
							}

							if (!t7.isValid<Arg7>())
							{
								std::cout << "Arg7 invalid" << std::endl;
							}

							if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
								!t6.isValid<Arg6>() || !t7.isValid<Arg7>())
								return myVariant();

							auto v1 = t1.get_pointer<Arg1>();
							auto v2 = t2.get_pointer<Arg2>();
							auto v3 = t3.get_pointer<Arg3>();
							auto v4 = t4.get_pointer<Arg4>();
							auto v5 = t5.get_pointer<Arg5>();
							auto v6 = t6.get_pointer<Arg6>();
							auto v7 = t7.get_pointer<Arg7>();
							if constexpr (std::is_same_v<return_t, void>) {
								(pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7);
								return myVariant();
							}
							else
							return (pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6, *v7);
						}else{
							if constexpr (getFunparameters<T>::num == 6)
							{
								using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
								using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
								using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
								using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
								using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
								using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;

								if (!t1.isValid<Arg1>())
								{
									std::cout << "Arg1 invalid" << std::endl;
								}

								if (!t2.isValid<Arg2>())
								{
									std::cout << "Arg2 invalid" << std::endl;
								}

								if (!t3.isValid<Arg3>())
								{
									std::cout << "Arg3 invalid" << std::endl;
								}

								if (!t4.isValid<Arg4>())
								{
									std::cout << "Arg4 invalid" << std::endl;
								}

								if (!t5.isValid<Arg5>())
								{
									std::cout << "Arg5 invalid" << std::endl;
								}

								if (!t6.isValid<Arg6>())
								{
									std::cout << "Arg6 invalid" << std::endl;
								}

								if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
									!t6.isValid<Arg6>() )
									return myVariant();

								auto v1 = t1.get_pointer<Arg1>();
								auto v2 = t2.get_pointer<Arg2>();
								auto v3 = t3.get_pointer<Arg3>();
								auto v4 = t4.get_pointer<Arg4>();
								auto v5 = t5.get_pointer<Arg5>();
								auto v6 = t6.get_pointer<Arg6>();
								if constexpr (std::is_same_v<return_t, void>) {
									(pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6);
									return myVariant();
								}
								else
									return (pobj->*f)(*v1, *v2, *v3, *v4, *v5, *v6);
							}
							else
							{
								if constexpr (getFunparameters<T>::num == 5)
								{
									using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
									using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
									using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
									using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
									using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;

									if (!t1.isValid<Arg1>())
									{
										std::cout << "Arg1 invalid" << std::endl;
									}

									if (!t2.isValid<Arg2>())
									{
										std::cout << "Arg2 invalid" << std::endl;
									}

									if (!t3.isValid<Arg3>())
									{
										std::cout << "Arg3 invalid" << std::endl;
									}

									if (!t4.isValid<Arg4>())
									{
										std::cout << "Arg4 invalid" << std::endl;
									}

									if (!t5.isValid<Arg5>())
									{
										std::cout << "Arg5 invalid" << std::endl;
									}

									if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>())
										return myVariant();

									auto v1 = t1.get_pointer<Arg1>();
									auto v2 = t2.get_pointer<Arg2>();
									auto v3 = t3.get_pointer<Arg3>();
									auto v4 = t4.get_pointer<Arg4>();
									auto v5 = t5.get_pointer<Arg5>();
									if constexpr (std::is_same_v<return_t, void>) {
										(pobj->*f)(*v1, *v2, *v3, *v4, *v5);
										return myVariant();
									}
									else
										return (pobj->*f)(*v1, *v2, *v3, *v4, *v5);
								}else{
									if constexpr (getFunparameters<T>::num == 4)
									{
										using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
										using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
										using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
										using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;

										if (!t1.isValid<Arg1>())
										{
											std::cout << "Arg1 invalid" << std::endl;
										}

										if (!t2.isValid<Arg2>())
										{
											std::cout << "Arg2 invalid" << std::endl;
										}

										if (!t3.isValid<Arg3>())
										{
											std::cout << "Arg3 invalid" << std::endl;
										}

										if (!t4.isValid<Arg4>())
										{
											std::cout << "Arg4 invalid" << std::endl;
										}


										if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>())
											return myVariant();

										auto v1 = t1.get_pointer<Arg1>();
										auto v2 = t2.get_pointer<Arg2>();
										auto v3 = t3.get_pointer<Arg3>();
										auto v4 = t4.get_pointer<Arg4>();
										if constexpr (std::is_same_v<return_t, void>) {
											(pobj->*f)(*v1, *v2, *v3, *v4);
											return myVariant();
										}
										else
											return (pobj->*f)(*v1, *v2, *v3, *v4);
									}else{
										if constexpr (getFunparameters<T>::num == 3)
										{
											using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
											using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
											using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;

											if (!t1.isValid<Arg1>())
											{
												std::cout << "Arg1 invalid" << std::endl;
											}

											if (!t2.isValid<Arg2>())
											{
												std::cout << "Arg2 invalid" << std::endl;
											}

											if (!t3.isValid<Arg3>())
											{
												std::cout << "Arg3 invalid" << std::endl;
											}

											if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>())
												return myVariant();

											auto v1 = t1.get_pointer<Arg1>();
											auto v2 = t2.get_pointer<Arg2>();
											auto v3 = t3.get_pointer<Arg3>();
											if constexpr (std::is_same_v<return_t, void>) {
												(pobj->*f)(*v1, *v2, *v3);
												return myVariant();
											}
											else
												return (pobj->*f)(*v1, *v2, *v3);
										}else{
											if constexpr (getFunparameters<T>::num == 2)
											{
												using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
												using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;

												if (!t1.isValid<Arg1>())
												{
													std::cout << "Arg1 invalid" << std::endl;
												}

												if (!t2.isValid<Arg2>())
												{
													std::cout << "Arg2 invalid" << std::endl;
												}

												if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>())
													return myVariant();

												auto v1 = t1.get_pointer<Arg1>();
												auto v2 = t2.get_pointer<Arg2>();
												if constexpr (std::is_same_v<return_t, void>) {
													(pobj->*f)(*v1, *v2);
													return myVariant();
												}
												else
													return (pobj->*f)(*v1, *v2);
											}else
											{
												if constexpr (getFunparameters<T>::num == 1)
												{
													using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;

													if (!t1.isValid<Arg1>())
													{
														std::cout << "Arg1 invalid" << std::endl;
													}

													if (!t1.isValid<Arg1>())
														return myVariant();

													auto v1 = t1.get_pointer<Arg1>();
													if constexpr (std::is_same_v<return_t, void>) {
														(pobj->*f)(*v1);
														return myVariant();
													}
													else
														return (pobj->*f)(*v1);
												}else{
													if constexpr (getFunparameters<T>::num == 0){
														if constexpr (std::is_same_v<return_t, void>) {
															(pobj->*f)();
															return myVariant();
														}else
															return (pobj->*f)();
													}else{
														return myVariant();
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		
		static myVariant execute_wrapperPtr(myVariant t0,
			myVariant t1 = myVariant(),
			myVariant t2 = myVariant(),
			myVariant t3 = myVariant(),
			myVariant t4 = myVariant(),
			myVariant t5 = myVariant(),
			myVariant t6 = myVariant(),
			myVariant t7 = myVariant(),
			myVariant t8 = myVariant(),
			myVariant t9 = myVariant(),
			myVariant t10 = myVariant()
		) {
			using obj_t = typename getFunparameters<T>::class_t;
			obj_t* pobject = nullptr;
			if (t0.isValid<obj_t*>()) {
				pobject = t0.get<obj_t*>();
			}
			if (t0.isValid<std::shared_ptr<obj_t>>()) {
				auto ptr = t0.get<std::shared_ptr<obj_t>>();
				pobject = ptr.get();
			}
			return execute_ptr(pobject, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
		}

		static myVariant execute_cstyle(
			myVariant t1 = myVariant(),
			myVariant t2 = myVariant(),
			myVariant t3 = myVariant(),
			myVariant t4 = myVariant(),
			myVariant t5 = myVariant(),
			myVariant t6 = myVariant(),
			myVariant t7 = myVariant(),
			myVariant t8 = myVariant(),
			myVariant t9 = myVariant(),
			myVariant t10 = myVariant()
		)
		{	
			using return_t = typename getFunparameters<T>::ret_t;
			if constexpr (getFunparameters<T>::num == 10)
			{
				using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
				using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
				using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
				using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
				using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
				using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
				using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
				using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;
				using Arg9 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 8>>;
				using Arg10 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 9>>;


				if (!t1.isValid<Arg1>())
				{
					std::cout << "Arg1 invalid" << std::endl;
				}

				if (!t2.isValid<Arg2>())
				{
					std::cout << "Arg2 invalid" << std::endl;
				}

				if (!t3.isValid<Arg3>())
				{
					std::cout << "Arg3 invalid" << std::endl;
				}

				if (!t4.isValid<Arg4>())
				{
					std::cout << "Arg4 invalid" << std::endl;
				}

				if (!t5.isValid<Arg5>())
				{
					std::cout << "Arg5 invalid" << std::endl;
				}

				if (!t6.isValid<Arg6>())
				{
					std::cout << "Arg6 invalid" << std::endl;
				}

				if (!t7.isValid<Arg7>())
				{
					std::cout << "Arg7 invalid" << std::endl;
				}

				if (!t8.isValid<Arg8>())
				{
					std::cout << "Arg8 invalid" << std::endl;
				}

				if (!t9.isValid<Arg9>())
				{
					std::cout << "Arg9 invalid" << std::endl;
				}

				if (!t10.isValid<Arg10>())
				{
					std::cout << "Arg10 invalid" << std::endl;
				}

				if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
					!t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>() || !t9.isValid<Arg9>() || !t10.isValid<Arg10>())
					return myVariant();

				auto v1 = t1.get_pointer<Arg1>();
				auto v2 = t2.get_pointer<Arg2>();
				auto v3 = t3.get_pointer<Arg3>();
				auto v4 = t4.get_pointer<Arg4>();
				auto v5 = t5.get_pointer<Arg5>();
				auto v6 = t6.get_pointer<Arg6>();
				auto v7 = t7.get_pointer<Arg7>();
				auto v8 = t8.get_pointer<Arg8>();
				auto v9 = t9.get_pointer<Arg9>();
				auto v10 = t10.get<Arg10>();
				if constexpr (std::is_same_v<return_t, void>) {
					f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9, *v10);
					return myVariant();
				}
				else
					return f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9, *v10);
			}
			else
			{
				if constexpr (getFunparameters<T>::num == 9)
				{
					using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
					using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
					using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
					using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
					using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
					using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
					using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
					using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;
					using Arg9 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 8>>;

					if (!t1.isValid<Arg1>())
					{
						std::cout << "Arg1 invalid" << std::endl;
					}

					if (!t2.isValid<Arg2>())
					{
						std::cout << "Arg2 invalid" << std::endl;
					}

					if (!t3.isValid<Arg3>())
					{
						std::cout << "Arg3 invalid" << std::endl;
					}

					if (!t4.isValid<Arg4>())
					{
						std::cout << "Arg4 invalid" << std::endl;
					}

					if (!t5.isValid<Arg5>())
					{
						std::cout << "Arg5 invalid" << std::endl;
					}

					if (!t6.isValid<Arg6>())
					{
						std::cout << "Arg6 invalid" << std::endl;
					}

					if (!t7.isValid<Arg7>())
					{
						std::cout << "Arg7 invalid" << std::endl;
					}

					if (!t8.isValid<Arg8>())
					{
						std::cout << "Arg8 invalid" << std::endl;
					}

					if (!t9.isValid<Arg9>())
					{
						std::cout << "Arg9 invalid" << std::endl;
					}

					if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
						!t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>() || !t9.isValid<Arg9>())
						return myVariant();

					auto v1 = t1.get_pointer<Arg1>();
					auto v2 = t2.get_pointer<Arg2>();
					auto v3 = t3.get_pointer<Arg3>();
					auto v4 = t4.get_pointer<Arg4>();
					auto v5 = t5.get_pointer<Arg5>();
					auto v6 = t6.get_pointer<Arg6>();
					auto v7 = t7.get_pointer<Arg7>();
					auto v8 = t8.get_pointer<Arg8>();
					auto v9 = t9.get_pointer<Arg9>();
					if constexpr (std::is_same_v<return_t, void>) {
						f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9);
						return myVariant();
					}
					else
						return f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8, *v9);
				}
				else {
					if constexpr (getFunparameters<T>::num == 8)
					{
						using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
						using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
						using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
						using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
						using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
						using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
						using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;
						using Arg8 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 7>>;

						if (!t1.isValid<Arg1>())
						{
							std::cout << "Arg1 invalid" << std::endl;
						}

						if (!t2.isValid<Arg2>())
						{
							std::cout << "Arg2 invalid" << std::endl;
						}

						if (!t3.isValid<Arg3>())
						{
							std::cout << "Arg3 invalid" << std::endl;
						}

						if (!t4.isValid<Arg4>())
						{
							std::cout << "Arg4 invalid" << std::endl;
						}

						if (!t5.isValid<Arg5>())
						{
							std::cout << "Arg5 invalid" << std::endl;
						}

						if (!t6.isValid<Arg6>())
						{
							std::cout << "Arg6 invalid" << std::endl;
						}

						if (!t7.isValid<Arg7>())
						{
							std::cout << "Arg7 invalid" << std::endl;
						}

						if (!t8.isValid<Arg8>())
						{
							std::cout << "Arg8 invalid" << std::endl;
						}

						if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
							!t6.isValid<Arg6>() || !t7.isValid<Arg7>() || !t8.isValid<Arg8>())
							return myVariant();

						auto v1 = t1.get_pointer<Arg1>();
						auto v2 = t2.get_pointer<Arg2>();
						auto v3 = t3.get_pointer<Arg3>();
						auto v4 = t4.get_pointer<Arg4>();
						auto v5 = t5.get_pointer<Arg5>();
						auto v6 = t6.get_pointer<Arg6>();
						auto v7 = t7.get_pointer<Arg7>();
						auto v8 = t8.get_pointer<Arg8>();
						if constexpr (std::is_same_v<return_t, void>) {
							f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8);
							return myVariant();
						}
						else
							return f(*v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8);
					}
					else {
						if constexpr (getFunparameters<T>::num == 7)
						{
							using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
							using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
							using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
							using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
							using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
							using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;
							using Arg7 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 6>>;

							if (!t1.isValid<Arg1>())
							{
								std::cout << "Arg1 invalid" << std::endl;
							}

							if (!t2.isValid<Arg2>())
							{
								std::cout << "Arg2 invalid" << std::endl;
							}

							if (!t3.isValid<Arg3>())
							{
								std::cout << "Arg3 invalid" << std::endl;
							}

							if (!t4.isValid<Arg4>())
							{
								std::cout << "Arg4 invalid" << std::endl;
							}

							if (!t5.isValid<Arg5>())
							{
								std::cout << "Arg5 invalid" << std::endl;
							}

							if (!t6.isValid<Arg6>())
							{
								std::cout << "Arg6 invalid" << std::endl;
							}

							if (!t7.isValid<Arg7>())
							{
								std::cout << "Arg7 invalid" << std::endl;
							}

							if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
								!t6.isValid<Arg6>() || !t7.isValid<Arg7>())
								return myVariant();

							auto v1 = t1.get_pointer<Arg1>();
							auto v2 = t2.get_pointer<Arg2>();
							auto v3 = t3.get_pointer<Arg3>();
							auto v4 = t4.get_pointer<Arg4>();
							auto v5 = t5.get_pointer<Arg5>();
							auto v6 = t6.get_pointer<Arg6>();
							auto v7 = t7.get_pointer<Arg7>();
							if constexpr (std::is_same_v<return_t, void>) {
								f(*v1, *v2, *v3, *v4, *v5, *v6, *v7);
								return myVariant();
							}
							else
								return f(*v1, *v2, *v3, *v4, *v5, *v6, *v7);
						}
						else {
							if constexpr (getFunparameters<T>::num == 6)
							{
								using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
								using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
								using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
								using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
								using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;
								using Arg6 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 5>>;

								if (!t1.isValid<Arg1>())
								{
									std::cout << "Arg1 invalid" << std::endl;
								}

								if (!t2.isValid<Arg2>())
								{
									std::cout << "Arg2 invalid" << std::endl;
								}

								if (!t3.isValid<Arg3>())
								{
									std::cout << "Arg3 invalid" << std::endl;
								}

								if (!t4.isValid<Arg4>())
								{
									std::cout << "Arg4 invalid" << std::endl;
								}

								if (!t5.isValid<Arg5>())
								{
									std::cout << "Arg5 invalid" << std::endl;
								}

								if (!t6.isValid<Arg6>())
								{
									std::cout << "Arg6 invalid" << std::endl;
								}

								if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>() ||
									!t6.isValid<Arg6>())
									return myVariant();

								auto v1 = t1.get_pointer<Arg1>();
								auto v2 = t2.get_pointer<Arg2>();
								auto v3 = t3.get_pointer<Arg3>();
								auto v4 = t4.get_pointer<Arg4>();
								auto v5 = t5.get_pointer<Arg5>();
								auto v6 = t6.get_pointer<Arg6>();
								if constexpr (std::is_same_v<return_t, void>) {
									f(*v1, *v2, *v3, *v4, *v5, *v6);
									return myVariant();
								}
								else
									return f(*v1, *v2, *v3, *v4, *v5, *v6);
							}
							else
							{
								if constexpr (getFunparameters<T>::num == 5)
								{
									using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
									using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
									using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
									using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;
									using Arg5 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 4>>;

									if (!t1.isValid<Arg1>())
									{
										std::cout << "Arg1 invalid" << std::endl;
									}

									if (!t2.isValid<Arg2>())
									{
										std::cout << "Arg2 invalid" << std::endl;
									}

									if (!t3.isValid<Arg3>())
									{
										std::cout << "Arg3 invalid" << std::endl;
									}

									if (!t4.isValid<Arg4>())
									{
										std::cout << "Arg4 invalid" << std::endl;
									}

									if (!t5.isValid<Arg5>())
									{
										std::cout << "Arg5 invalid" << std::endl;
									}

									if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>() || !t5.isValid<Arg5>())
										return myVariant();

									auto v1 = t1.get_pointer<Arg1>();
									auto v2 = t2.get_pointer<Arg2>();
									auto v3 = t3.get_pointer<Arg3>();
									auto v4 = t4.get_pointer<Arg4>();
									auto v5 = t5.get_pointer<Arg5>();
									if constexpr (std::is_same_v<return_t, void>) {
										f(*v1, *v2, *v3, *v4, *v5);
										return myVariant();
									}
									else
										return f(*v1, *v2, *v3, *v4, *v5);
								}
								else {
									if constexpr (getFunparameters<T>::num == 4)
									{
										using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
										using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
										using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
										using Arg4 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 3>>;

										if (!t1.isValid<Arg1>())
										{
											std::cout << "Arg1 invalid" << std::endl;
										}

										if (!t2.isValid<Arg2>())
										{
											std::cout << "Arg2 invalid" << std::endl;
										}

										if (!t3.isValid<Arg3>())
										{
											std::cout << "Arg3 invalid" << std::endl;
										}

										if (!t4.isValid<Arg4>())
										{
											std::cout << "Arg4 invalid" << std::endl;
										}


										if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>() || !t4.isValid<Arg4>())
											return myVariant();

										auto v1 = t1.get_pointer<Arg1>();
										auto v2 = t2.get_pointer<Arg2>();
										auto v3 = t3.get_pointer<Arg3>();
										auto v4 = t4.get_pointer<Arg4>();
										if constexpr (std::is_same_v<return_t, void>) {
											f(*v1, *v2, *v3, *v4);
											return myVariant();
										}
										else
											return f(*v1, *v2, *v3, *v4);
									}
									else {
										if constexpr (getFunparameters<T>::num == 3)
										{
											using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
											using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;
											using Arg3 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 2>>;
											
											if (!t1.isValid<Arg1>())
											{
												std::cout << "Arg1 invalid" << std::endl;
											}

											if (!t2.isValid<Arg2>())
											{
												std::cout << "Arg2 invalid" << std::endl;
											}

											if (!t3.isValid<Arg3>())
											{
												std::cout << "Arg3 invalid" << std::endl;
											}

											if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>() || !t3.isValid<Arg3>())
												return myVariant();

											auto v1 = t1.get_pointer<Arg1>();
											auto v2 = t2.get_pointer<Arg2>();
											auto v3 = t3.get_pointer<Arg3>();
											if constexpr (std::is_same_v<return_t, void>) {
												f(*v1, *v2, *v3);
												return myVariant();
											}
											else
												return f(*v1, *v2, *v3);
										}
										else {
											if constexpr (getFunparameters<T>::num == 2)
											{
												using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;
												using Arg2 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 1>>;

												if (!t1.isValid<Arg1>())
												{
													std::cout << "Arg1 invalid" << std::endl;
												}

												if (!t2.isValid<Arg2>())
												{
													std::cout << "Arg2 invalid" << std::endl;
												}

												if (!t1.isValid<Arg1>() || !t2.isValid<Arg2>())
													return myVariant();

												auto v1 = t1.get_pointer<Arg1>();
												auto v2 = t2.get_pointer<Arg2>();
												if constexpr (std::is_same_v<return_t, void>) {
													f(*v1, *v2);
													return myVariant();
												}
												else {
													auto tt = t1.get<Arg1>();
													auto m = *v1;
													return f(*v1, *v2);
												}		
											}
											else
											{
												if constexpr (getFunparameters<T>::num == 1)
												{
													using Arg1 = convert_ref_t<TL::TL_NthElement_t<typename getFunparameters<T>::parameter_list_t, 0>>;	

													if (!t1.isValid<Arg1>())
													{
														std::cout << "Arg1 invalid" << std::endl;
													}

													if (!t1.isValid<Arg1>())
														return myVariant();

													auto v1 = t1.get_pointer<Arg1>();
													if constexpr (std::is_same_v<return_t, void>) {
														f(*v1);
														return myVariant();
													}
													else
														return f(*v1);
												}
												else {
													if constexpr (getFunparameters<T>::num == 0) {
														if constexpr (std::is_same_v<return_t, void>) {
															f();
															return myVariant();
														}
														else
															return f();
													}
													else {
														return myVariant();
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
};
}
#endif